﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Web;
using System.Web.Mvc;

namespace SuperStar.Helper
{
    public class CaptchaResult : ActionResult
    {
        public string CaptchaText;
        public CaptchaResult(string captchaText)
        {
            CaptchaText = captchaText;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            var c = new Captcha {Text = CaptchaText, Width = 140, Height = 40, FamilyName = "Century Schoobook"};
            var cb = context.HttpContext;
            cb.Response.Clear();
            cb.Response.ContentType = "image/jpeg";
            c.Image.Save(cb.Response.OutputStream, ImageFormat.Jpeg);
            c.Dispose();
        }
        public class Captcha
        {
            private string _text;
            private int _width;
            private int _height;
            private string _familyName;
            private Bitmap _image;
            private static readonly Random Random = new Random();

            public string FamilyName
            {
                get { return _familyName; }
                set { _familyName = value; }
            }
            public string Text
            {
                get { return this._text; }
                set { _text = value; }
            }
            public Bitmap Image
            {
                get
                {
                    if (!string.IsNullOrEmpty(_text) && _height > 0 && _width > 0)
                        GenerateImage();
                    return this._image;
                }
            }
            public int Width
            {
                get { return this._width; }
                set { _width = value; }
            }
            public int Height
            {
                get { return this._height; }
                set { _height = value; }
            }

            public Captcha()
            {

            }

            ~Captcha()
            {
                Dispose(false);
            }

            public void Dispose()
            {
                GC.SuppressFinalize(this);
                this.Dispose(true);
            }

            protected virtual void Dispose(bool disposing)
            {
                if (disposing)
                    this._image.Dispose();
            }

            private void SetDimensions(int width, int height)
            {
                if (width <= 0)
                    throw new ArgumentOutOfRangeException("width", width, "Argument out of range, must be greater than zero.");
                if (height <= 0)
                    throw new ArgumentOutOfRangeException("height", height, "Argument out of range, must be greater than zero.");
                this._width = width;
                this._height = height;
            }

            private void SetFamilyName(string familyName)
            {
                try
                {
                    var font = new Font(this._familyName, 16F);
                    this._familyName = familyName;
                    font.Dispose();
                }
                catch
                {
                    this._familyName = FontFamily.GenericSerif.Name;
                }
            }

            public void GenerateImage()
            {
                //---- WITHOUT an image for the background ------

                // Create a new 32-bit bitmap image.
                var bitmap = new Bitmap(this._width, this._height, PixelFormat.Format32bppArgb);

                // Create a graphics object for drawing.
                var g = Graphics.FromImage(bitmap);
                g.SmoothingMode = SmoothingMode.AntiAlias;
                var rect = new Rectangle(0, 0, this._width, this._height);

                // Fill in the background.
                //HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, ColorTranslator.FromHtml("#607f20"), ColorTranslator.FromHtml("#ffea00"));
                //HatchBrush hatchBrush = new HatchBrush(HatchStyle.Trellis, ColorTranslator.FromHtml("#ffffff"), ColorTranslator.FromHtml("#607f20"));
                var hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.FromArgb(114, 172, 236), Color.FromArgb(161, 214, 255));
                //Color.FromArgb(76,136,198)    medium
                //Color.FromArgb(0,79,136)      dark
                //Color.FromArgb(114,172,236)   medium-light
                //Color.FromArgb(135,188,254)   light
                //Color.FromArgb(161,214,255)   really light
                g.FillRectangle(hatchBrush, rect);

                //---- WITH a background image ----------
                //string bgpath = HttpContext.Current.Server.MapPath("CaptchaBG.bmp");
                //Bitmap bitmap = new Bitmap(bgpath);
                //Graphics g = Graphics.FromImage(bitmap);
                //g.SmoothingMode = SmoothingMode.AntiAlias;
                //HatchBrush hatchBrush = null;
                //Rectangle rect = new Rectangle(0, 0, this.width, this.height);

                //-----------------------------------------

                // Set up the text font.
                SizeF size;
                float fontSize = this._height + 4;
                Font font;
                // Adjust the font size until the text fits within the image.
                do
                {
                    fontSize--;
                    font = new Font(this._familyName, fontSize, FontStyle.Bold);
                    size = g.MeasureString(this._text, font);
                } while (size.Width > this._width);

                // Set up the text format.
                var format = new StringFormat();
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;

                // Create a path using the text and warp it randomly.
                var path = new GraphicsPath();
                path.AddString(this._text, font.FontFamily, (int)font.Style, font.Size, rect, format);
                float v = 4F;
                PointF[] points =
                {
                    new PointF(Random.Next(this._width) / v, Random.Next(this._height) / v),
                    new PointF(this._width - Random.Next(this._width) / v, Random.Next(this._height) / v),
                    new PointF(Random.Next(this._width) / v, this._height - Random.Next(this._height) / v),
                    new PointF(this._width - Random.Next(this._width) / v, this._height - Random.Next(this._height) / v)
                };
                Matrix matrix = new Matrix();
                matrix.Translate(0F, 0F);
                path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);

                // Draw the text.
                hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, ColorTranslator.FromHtml("#000000"), ColorTranslator.FromHtml("#000000"));
                //  white numbers
                //  hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, ColorTranslator.FromHtml("#ffffff"), ColorTranslator.FromHtml("#ffffff"));
                //  yellow numbers
                //hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, ColorTranslator.FromHtml("#ffea00"), ColorTranslator.FromHtml("#ffea00"));
                g.FillPath(hatchBrush, path);

                //// Add some random noise.
                int m = Math.Max(this._width, this._height);
                for (int i = 0; i < (int)(this._width * this._height / 30F); i++)
                {
                    int x = Random.Next(this._width);
                    int y = Random.Next(this._height);
                    int w = Random.Next(m / 50);
                    int h = Random.Next(m / 50);
                    g.FillEllipse(hatchBrush, x, y, w, h);
                }

                // Clean up.
                font.Dispose();
                hatchBrush.Dispose();
                g.Dispose();

                // Set the image.
                this._image = bitmap;
            }

            public static string GenerateRandomCode()
            {
                string s = "";
                for (int i = 0; i < 4; i++)
                    s = String.Concat(s, Random.Next(10).ToString());
                return s;
            }
        }
    }
}
